/* 
 * Autores:
 *      Jonathan Lopez  11106
 *      Jorge Martínez  11237
 * 
 * Archivo: RegBarcos.java
 * Última Revision: $Rev: 66 $
 *      Fecha: $Date: 2011-09-18 16:14:18 +0000 (Sun, 18 Sep 2011) $
 */ 

package Manejo.Transporte.Registros;

import java.util.HashMap;
import java.util.ArrayList;

import Manejo.Transporte.Barco;
import Archivador.*;
import Manejo.Transporte.Viaje;
import java.util.Date;

/**
 * Registro de todos los Barcos que existen en el programa
 * 
 * @author Jonathan López
 * @author Jorge Martinez
 */
public class RegBarcos
{
    private HashMap<ID, Barco> barcos;
    private HashMap<String, ID> nombreBarcos;
    private String nombreRegistro = "RegistroBarcos";

    /**
     * Construye el registro de Barcos
     */
    public RegBarcos()
    {
        barcos = new HashMap<ID, Barco>();
        nombreBarcos = new HashMap<String, ID>();
    }
    
    /**
     * Lee los Barcos desde la base de datos
     */
    public void inicializar( Registros registros )
    {
        // Leer los Barcos de la base de datos
        String[] infoBarcos = Archivador.leerRegistro(nombreRegistro);
        if( infoBarcos != null ){
            for( String linea: infoBarcos ){
                if( !linea.equals("") && !leerBarco( linea, registros ) )
                    System.out.println("*ERROR RegBarcos* - No se pudo leer Barco");
            }
        }
    }
    
    /**
     * Guarda el registro de Barcos
     */
    public void guardarTodo(){
        // Serializa todos los Barcos
        ArrayList<String> lineaBarcos = new ArrayList<String>();
        
        for( String nombreBarco: nombreBarcos.keySet() ){
            ID idBarco = nombreBarcos.get( nombreBarco );
            
            String srIdentificador = "[" + nombreBarco + iArchivable.separador +
                    idBarco.guardar() + "]";
            String srPuerto = barcos.get(idBarco).guardar();
            
            lineaBarcos.add( srIdentificador + iArchivable.separadorObjetos +
                    srPuerto );
        }
        
        // Guarda el registro
        if( lineaBarcos.isEmpty() )
            lineaBarcos.add("");
        
        Archivador.guardarRegistro(nombreRegistro,
                lineaBarcos.toArray( new String[0] ));
    }
    
    /**
     * Agrega u nuevo Barco al registro y le asigna un ID
     * @param nuevoBarco Barco a agregar
     * @return nuevo ID del Barco
     */
    public ID agregarBarco( Barco nuevoBarco, String nombre )
    {
        // Validar
        if( nuevoBarco == null || nombre.equals("") )
            return ID.idNulo;
        
        ID nuevoID = GeneradorID.nuevoID();
        while( barcos.containsKey( nuevoID ) ){
            // Muy improbable
            // TODO: notificar al log por cada uno de estos casos
            nuevoID = GeneradorID.nuevoID();
        }
        
        barcos.put( nuevoID, nuevoBarco );
        nombreBarcos.put( nombre, nuevoID );
        return nuevoID;
    }
    
    /**
     * Regresa el Barco asociada con el ID dado
     * @param idBarco ID del Barco a buscar
     * @return Barco asociado al ID o null si no se encuentra
     */
    public Barco obtenerBarco( ID idBarco )
    {
        return barcos.get( idBarco );
    }
    
    /**
     * Regresa el Barco asociado con un nombre dado.
     * @param nombre nombre del Barco asociado en el registro.
     * @return Barco asociado, o null si no existe el Barco
     */
    public Barco obtenerBarco( String nombre )
    {
        return obtenerBarco( nombreBarcos.get( nombre ) );
    }
    
    /**
     * @param idBarco
     * @return Regresa el nombre del Barco dado, o "" si el Barco no existe.
     */
    public String obtenerNombre( ID idBarco ){
        for( String nombreActual : nombreBarcos.keySet() ){
            if( nombreBarcos.get(nombreActual).equals(idBarco) )
                return nombreActual;
        }
        return "";
    }
    
    /**
     * Regresa un arreglo con todos los Barcos contenidos en el registro
     * @return Barco[] con todos los Barcos en el registro
     */
    public Barco[] obtenerTodosBarcos()
    {
        return barcos.values().toArray( new Barco[0] );
    }
    
    /**
     * Regresa un arreglo con los nombre de todos los Barcos registrados en
     * el registro.
     * @return String [] con todos los nombres de Barcos
     */
    public String[] obtenerNombresDeBarcos()
    {
        return nombreBarcos.keySet().toArray( new String[0] );
    }
    
    /**
     * Regresa el ID de un Barco, por su referencia.
     * @param barcoObjetivo 
     * @return ID del Barco
     */
    public ID obtenerID( Barco barcoObjetivo )
    {
        for( ID id: barcos.keySet() ){
            if( barcos.get(id).equals( barcoObjetivo) )
                return id;
        }
        
        return ID.idNulo;
    }
    
    /**
     * Regresa el ID de un Barco, por su nombre.
     * @param nombreBarco Nombre del Barco a obtener
     * @return ID del Barco, o idNulo si el Barco no existe.
     */
    public ID obtenerID( String nombreBarco ){
        if( nombreBarcos.containsKey(nombreBarco) )
            return nombreBarcos.get(nombreBarco);
        else
            return ID.idNulo;
    }
    
    /**
     * Elimina un Barco del registro según su ID
     * @param idBarco ID del Barco a eliminar
     * @return el Barco asociada al ID dado, o null si no existía
     */
    public Barco eliminarBarco( ID idBarco )
    {
        // Eliminar la referencia de nombre si existe
        if( nombreBarcos.containsValue( idBarco ) ){
            nombreBarcos.values().remove( idBarco );
            return barcos.remove( idBarco );
        }
        else
            return null;
    }
    
    /**
     * Avanza todos los Barcos a la fecha dada, dejando y trayendo los
     * Contenedores en sus respectivos Puertos.
     * @param fecha 
     */
    public void avanzarBarcos( Date fecha ){
        for (ID idBarco : barcos.keySet()) {
            Barco barcoActual = barcos.get(idBarco);
            Viaje viajeBarco = barcoActual.obtenerViaje();
            
            if( viajeBarco != null )
                viajeBarco.avanzarPuerto(fecha, idBarco);
        }
    }
    
    /**
     * Lee un solo Barco a partir de una línea del registro
     * @param linea
     * @param registroContenedores
     * @param registroRutas
     * @param registroBarcos
     * @param registroPuertos
     * @return 
     */
    private boolean leerBarco( String linea,
            Registros registros )
    {
        String[] partes = linea.split( iArchivable.separadorObjetos, 2 );
        if( partes.length != 2 )
            return false;
        
        // Interpreta el ID del Barco
        String srIdentificador = Util.eliminarExtremos( partes[0] );
        String[] partesIdentificador = srIdentificador.split( iArchivable.separador );
        if( partesIdentificador.length != 2 )
            return false;
        
        String nombre = partesIdentificador[0];
        ID idBarco = ID.parseID( partesIdentificador[1] );
        if( idBarco.equals( ID.idNulo ) )
            return false;
        
        // Interpreta el Barco
        Barco barcoActual = Barco.parseBarco( partes[1], registros );
        if( barcoActual == null )
            return false;
        
        // Agrega el nuevo Barco
        barcos.put( idBarco, barcoActual );
        nombreBarcos.put( nombre, idBarco );
        return true;
    }
}
